package com.yuexin.project.wechat.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.yuexin.common.utils.AesCbcUtil;
import com.yuexin.common.utils.HttpRequest;
import com.yuexin.framework.aspectj.lang.annotation.Log;
import com.yuexin.framework.aspectj.lang.enums.BusinessType;
import com.yuexin.framework.aspectj.lang.enums.DataSourceType;
import com.yuexin.framework.datasource.DynamicDataSourceContextHolder;
import com.yuexin.framework.web.controller.BaseController;
import com.yuexin.framework.web.domain.AjaxResult;
import com.yuexin.framework.web.page.TableDataInfo;
import com.yuexin.project.abutment.domain.Company;
import com.yuexin.project.abutment.mapper.AbutmentMapper;
import com.yuexin.project.system.user.domain.User;
import com.yuexin.project.system.user.mapper.UserMapper;
import com.yuexin.project.wechat.domain.AuthUser;
import com.yuexin.project.wechat.service.IAuthUserService;
import io.swagger.annotations.Api;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import java.security.MessageDigest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * 微信用户授权 信息操作处理
 * 
 * @author yuexin
 * @date 2019-01-16
 */
@Controller
@RequestMapping("/meals/wechat")
@Api(value = "微信用户授权", description = "微信用户授权")
public class AuthUserController extends BaseController
{
	private static final Logger log = LoggerFactory.getLogger(AuthUserController.class);
    private String prefix = "meals/wechat";
	
	@Autowired
	private IAuthUserService authUserService;
	
	@Autowired
	private AbutmentMapper abutmentMapper;
	
	@Autowired
	private UserMapper userMapper;
	
	@RequiresPermissions("wechat:authUser:view")
	@GetMapping()
	public String authUser()
	{
	    return prefix + "/authUser";
	}
	
	/**
               * 解密用户敏感数据(登录服务器)
     *
     *  encryptedData 明文,加密数据
     *  iv            加密算法的初始向量
     *  code          用户允许登录后，回调内容会带上 code（有效期五分钟），开发者需要将 code 发送到开发者服务器后台，使用code 换取 session_key api，将 code 换成 openid 和 session_key
     * @return
     */
	@PostMapping("/decodeUserInfo")
	@ResponseBody
    public AjaxResult decodeUserInfo(@RequestBody Map<String,String> reqbody) {
		String encryptedData = reqbody.get("encryptedData");
		String iv = reqbody.get("iv");
		String code = reqbody.get("code");
		
		//DynamicDataSourceContextHolder.clearDateSoureType();
		//DynamicDataSourceContextHolder.setDateSoureType(DataSourceType.MASTER.name());
		
       /* String encryptedData = req.getParameter("encryptedData");
        String iv = req.getParameter("iv");
        String code = req.getParameter("code");*/
        
		System.out.println("encryptedData==="+encryptedData);
		System.out.println("iv==="+iv);
		System.out.println("code==="+code);
        //登录凭证不能为空
        if (code == null || code.length() == 0) {
            return error("code 不能为空");
        }
 
        //小程序唯一标识   (在微信小程序管理后台获取)
        String wxspAppid = "wx1901a094e639fb4e";
        //小程序的 app secret (在微信小程序管理后台获取)
        String wxspSecret = "50a6b8752799078a1d0acf638bd4ff9f";
        //授权（必填）
        String grant_type = "authorization_code";
 
 
        //////////////// 1、向微信服务器 使用登录凭证 code 获取 session_key 和 openid ////////////////
        //请求参数
        String params = "appid=" + wxspAppid + "&secret=" + wxspSecret + "&js_code=" + code + "&grant_type=" + grant_type;
        //发送请求
        String sr = HttpRequest.sendGet("https://api.weixin.qq.com/sns/jscode2session", params);
        //解析相应内容（转换成json对象）
        //JSONObject json = JSONObject.fromObject(sr);
        JSONObject json = JSONObject.parseObject(sr);
        System.out.println("json---"+json);
        //获取会话密钥（session_key）
        String session_key = json.get("session_key").toString();
        //用户的唯一标识（openid）
        //String openid = (String) json.get("openid");
 
        //////////////// 2、对encryptedData加密数据进行AES解密 ////////////////
        try {
            String result = AesCbcUtil.decrypt(encryptedData, session_key, iv, "UTF-8");
            if (null != result && result.length() > 0) {
                //map.put("status", 1);
                //map.put("msg", "解密成功");
                JSONObject userInfoJSON = JSONObject.parseObject(result);
                Map<String,Object> resultInfo = Maps.newHashMap();
                Map<String,Object> userInfo = Maps.newHashMap();
                userInfo.put("openId", userInfoJSON.get("openId"));
                userInfo.put("nickName", userInfoJSON.get("nickName"));
                userInfo.put("gender", userInfoJSON.get("gender"));
                userInfo.put("city", userInfoJSON.get("city"));
                userInfo.put("province", userInfoJSON.get("province"));
                userInfo.put("country", userInfoJSON.get("country"));
                userInfo.put("avatarUrl", userInfoJSON.get("avatarUrl"));
                userInfo.put("unionId", userInfoJSON.get("unionId"));
                //map.put("userInfo", userInfo);
                resultInfo.put("wechatUserInfo", userInfo);
				log.info("用户数据：", JSON.toJSONString(userInfo));
				System.out.println("resultInfo==="+resultInfo);
				//通过openId判断用户是否绑定,绑定后返回用户相关信息
				AuthUser authUser = authUserService.selectAuthUserByUnionId(userInfoJSON.getString("unionId"));
				resultInfo.put("authUserInfo", authUser);
                return success(resultInfo);
            }
        } catch (Exception e) {
            return error("解密失败");
        }
        //map.put("status", 0);
        //map.put("msg", "解密失败");
        return success();
    }
    
    /**
	 * 小程序首页登录（登录服务器）
	 * */
	@PostMapping("/loginMiniForLogon")
	@ResponseBody
    public AjaxResult loginMiniForLogon(@RequestBody Map<String,String> reqbody)
    {
		String companyAccount = reqbody.get("companyAccount");
		String loginName = reqbody.get("loginName");
		Company comp = abutmentMapper.selectCompanyByAccount(companyAccount);
		Map<String, Object> map = new HashMap<String, Object>();
		if(comp == null ) {
			//公司账号不存在
			map.put("status", "0");
		}else {
			map.put("status", "1");
			map.put("companyStatus", comp.getStatus());
			map.put("expiredDate", comp.getExpiredDate());
		}
		//判断订餐账号是否被绑定
		AuthUser loginUser = authUserService.selectAuthUserByLoginName(loginName);
		if(loginUser != null) {
			map.put("userBind", "1");
		}else {
			map.put("userBind", "0");
		}
		
		return success(map);
    }
	
	/**
	 * 小程序首页登录（应用服务器）
	 * */
	@PostMapping("/loginMiniForApplication")
	@ResponseBody
    public AjaxResult loginMiniForApplication(@RequestBody Map<String,String> reqbody)
    {
		String companyAccount = reqbody.get("companyAccount");
		String loginName = reqbody.get("loginName");
		String loginPwd = reqbody.get("loginPwd");
		String openId = reqbody.get("openId");
		String unionId = reqbody.get("unionId");
		
		Company comp = abutmentMapper.selectCompanyByAccount(companyAccount);
		String compId = comp.getCompId();
		User isUser = new User();
		isUser.setCompanyId(compId);
		isUser.setLoginName(loginName);
		List<User> userList = userMapper.selectUserList(isUser);
		Map<String, String> map = Maps.newHashMap();
		if(userList == null || userList.size() <= 0) {
			//用户不存在
			map.put("status", "2");
			return success(map);
		}
		User user = userMapper.selectUserByLoginName(loginName);
		if("2".equals(user.getDelFlag())) {
			//账号已被删除
			map.put("status", "3");
			return success(map);
		}
		
		if("1".equals(user.getStatus())) {
			//账号已被禁用
			map.put("status", "4");
			return success(map);
		}
		
		try {
			UsernamePasswordToken oaToken = new UsernamePasswordToken(loginName, loginPwd, "");
	        Subject subject = SecurityUtils.getSubject();
	        subject.login(oaToken);
		} catch (Exception e) {
			//用户或密码错误
			map.put("status", "5");
			return success(map);
		}
		
		//验证成功把用户信息会写到登录服务器
		AuthUser authUser = new AuthUser();
		authUser.setOpenId(openId);
		authUser.setUnionId(unionId);
		authUser.setComId(comp.getCompanyId());
		authUser.setCompanyAccount(companyAccount);
		authUser.setUserId(user.getUserId().intValue());
		authUser.setLoginName(loginName);
		authUser.setUserName(user.getUserName());
		authUser.setStatus("1");
		authUser.setAppId("wx1901a094e639fb4e");
		authUser.setCompId(comp.getCompId());
		boolean result = saveAuthUser(authUser);
		if(result) {
			map.put("status", "6");
			return success(map);
		}else {
			map.put("status", "7");
			return success(map);
		}
    }
	
	
	private boolean saveAuthUser(AuthUser user) {
		boolean result = false;
		DynamicDataSourceContextHolder.setDateSoureType(DataSourceType.SLAVE.name());
		AuthUser authUser = authUserService.selectAuthUserByUnionId(user.getUnionId());
		String loginName = user.getLoginName();
		AuthUser loginUser = authUserService.selectAuthUserByLoginName(loginName);
		
		//订餐账号若被绑定,则将原来的授权记录解绑
		if(loginUser != null) {
			loginUser.setStatus("2");
			authUserService.updateAuthUser(loginUser);
		}
		
		if(authUser == null) {
			authUserService.insertAuthUser(user);
		}else {
			//authUser.setStatus("1");
			Integer authId = authUser.getAuthId();
			user.setAuthId(authId);
			System.out.println("用户数据：" + JSON.toJSONString(user));
			authUserService.updateAuthUser(user);
		}
		result = true;
		DynamicDataSourceContextHolder.clearDateSoureType();
		DynamicDataSourceContextHolder.setDateSoureType(DataSourceType.MASTER.name());
		return result;
	}
	
	private boolean untyingAuthUser(String unionId) {
		boolean result = false;
		DynamicDataSourceContextHolder.setDateSoureType(DataSourceType.SLAVE.name());
		authUserService.untyingAuthUser(unionId);
		result = true;
		DynamicDataSourceContextHolder.clearDateSoureType();
		DynamicDataSourceContextHolder.setDateSoureType(DataSourceType.MASTER.name());
		return result;
	}
	
	/**
	 * 小程序用户解绑（应用服务器）
	 * */
	@PostMapping("/untying")
	@ResponseBody
    public AjaxResult untying(String unionId)
    {
		//String openId = reqbody.get("openId");
		Map<String, String> map = new HashMap<String, String>();
		boolean result = untyingAuthUser(unionId);
		if(result) {
			map.put("status", "1");
			return success(map);
		}else {
			map.put("status", "0");
			return success(map);
		}
    }
	
	private String getRandomString(int length){
	     String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
	     Random random=new Random();
	     StringBuffer sb=new StringBuffer();
	     for(int i=0;i<length;i++){
	       int number=random.nextInt(62);
	       sb.append(str.charAt(number));
	     }
	     return sb.toString();
	}
	
	/**
     * SHA1加密
     *
     * @param str
     * @return
     */
    public static String sha(String str) {
        if (str == null || str.length() == 0) {
            return null;
        }
        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                'a', 'b', 'c', 'd', 'e', 'f'};
        try {
            MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
            mdTemp.update(str.getBytes("UTF-8"));
            byte[] md = mdTemp.digest();
            int j = md.length;
            char buf[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
                buf[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(buf);
        } catch (Exception e) {
            return null;
        }
    }

	
	/**
	 * 小程序扫码,获取JSSDK配置信息
	 * */
	@PostMapping("/getJsSDKConfig")
	@ResponseBody
    public AjaxResult getJsSDKConfig(String url)
    {
        String appid = "wx39db65ac1b604856";
        String secret = "389e57698a9e54fc325286475d648c77";
        String grant_type = "client_credential";
		String access_token = getAccessToken(appid, secret, grant_type);
		String ticket = getJsapiTicket(access_token);
		
		String noncestr = getRandomString(8);//随机字符串
		String timestamp = String.valueOf(System.currentTimeMillis() / 1000);//时间戳
		
		System.out.println("ticket==="+ticket);
		System.out.println("noncestr==="+noncestr);
		System.out.println("timestamp==="+timestamp);
		System.out.println("url==="+url);
		
		//5、将参数排序并拼接字符串
		String str = "jsapi_ticket="+ticket+"&noncestr="+noncestr+"&timestamp="+timestamp+"&url="+url;
		//6、将字符串进行sha1加密
		String signature = sha(str);
		
		Map<String,String> map=new HashMap<String,String>();
		map.put("timestamp",timestamp);
		map.put("accessToken",access_token);
		map.put("ticket",ticket);
		map.put("noncestr",noncestr);
		map.put("signature",signature);
		return success(map);
    }
	
	private String getAccessToken(String appid,String secret,String grant_type) {
		String params = "appid=" + appid + "&secret=" + secret + "&grant_type=" + grant_type;
        String sr = HttpRequest.sendGet("https://api.weixin.qq.com/cgi-bin/token", params);
        JSONObject json = JSONObject.parseObject(sr);
        System.out.println("json-----"+json);
        String access_token = json.get("access_token").toString();
        return access_token;
	}
	
	private String getJsapiTicket(String access_token) {
		String params = "access_token=" + access_token + "&type=jsapi";
        String sr = HttpRequest.sendGet("https://api.weixin.qq.com/cgi-bin/ticket/getticket", params);
        JSONObject json = JSONObject.parseObject(sr);
        String ticket = json.get("ticket").toString();
        return ticket;
	}
	
	
	/**
	 * 查询微信用户授权列表
	 */
	@RequiresPermissions("wechat:authUser:list")
	@PostMapping("/list")
	@ResponseBody
	public TableDataInfo list(AuthUser authUser)
	{
		startPage();
        List<AuthUser> list = authUserService.selectAuthUserList(authUser);
		return getDataTable(list);
	}
	
	/**
	 * 新增微信用户授权
	 */
	@GetMapping("/add")
	public String add()
	{
	    return prefix + "/add";
	}
	
	/**
	 * 新增保存微信用户授权
	 */
	@RequiresPermissions("wechat:authUser:add")
	@Log(title = "微信用户授权", businessType = BusinessType.INSERT)
	@PostMapping("/add")
	@ResponseBody
	public AjaxResult addSave(AuthUser authUser)
	{		
		return toAjax(authUserService.insertAuthUser(authUser));
	}

	/**
	 * 修改微信用户授权
	 */
	@GetMapping("/edit/{authId}")
	public String edit(@PathVariable("authId") Integer authId, ModelMap mmap)
	{
		AuthUser authUser = authUserService.selectAuthUserById(authId);
		mmap.put("authUser", authUser);
	    return prefix + "/edit";
	}
	
	/**
	 * 修改保存微信用户授权
	 */
	@RequiresPermissions("wechat:authUser:edit")
	@Log(title = "微信用户授权", businessType = BusinessType.UPDATE)
	@PostMapping("/edit")
	@ResponseBody
	public AjaxResult editSave(AuthUser authUser)
	{		
		return toAjax(authUserService.updateAuthUser(authUser));
	}
	
	/**
	 * 删除微信用户授权
	 */
	@RequiresPermissions("wechat:authUser:remove")
	@Log(title = "微信用户授权", businessType = BusinessType.DELETE)
	@PostMapping( "/remove")
	@ResponseBody
	public AjaxResult remove(String ids)
	{		
		return toAjax(authUserService.deleteAuthUserByIds(ids));
	}
	
}
